<template>

	<scroll-view
		:scroll-x="true"
		:scroll-left="scrollLeft"
		scroll-with-animation
		class="u-tabs__wrapper__scroll-view"
		:show-scrollbar="false"
		ref="u-tabs__wrapper__scroll-view"
	>	 
		<view class="cate-tabs"
		 ref="u-tabs__wrapper__nav">
		 
			<view class="sub-cate"
			 :class="[ index==innerCurrent && 'active',`u-tabs__wrapper__nav__item-${index}`]"
			 v-for="(item,index) in list"  :key="index"
			@tap="clickHandler(item, index)"
			:ref="`u-tabs__wrapper__nav__item-${index}`"
			 >
				<text class="font-size14" > {{item.title}}</text>
			</view>
			 
		</view>
	</scroll-view>	
	
</template>

<script>
	export default{
		name : 'CateList',
		emits: ['click', 'change'],
		props:{
			list:{
				type:Array,
				default:[]
			},
			current:{
				type: Number,
				default: 0
			}
		},
		data(){
			return {
				scrollLeft : 0,
				innerCurrent : undefined,
			}
		},
		watch: {
			current: {
				immediate: true,
				handler (newValue, oldValue) {
					// 内外部值不相等时，才尝试移动滑块
					if (newValue !== this.innerCurrent) {
						this.innerCurrent = newValue
						this.$nextTick(() => {
							this.resize()
						})
					}
				}
			},
			//外部改变分类数据时，默认选中第一个分类
			list:{
				immediate: true,
				handler (newValue, oldValue) {
					 this.innerCurrent = undefined;					 
				}
			}
		},
		async mounted() {
			this.init()
		},
		
		methods:{
		   sleep(value = 30) {
				return new Promise((resolve) => {
					setTimeout(() => {
						resolve()
					}, value)
				})
			} ,
			clickHandler(item, index) {
				// 因为标签可能为disabled状态，所以click是一定会发出的，但是change事件是需要可用的状态才发出
				this.$emit('click', {
					...item,
					index
				})
				this.innerCurrent = index;
				this.resize()
				this.$emit('change', {
					...item,
					index
				})
			},
			init() {
				this.sleep().then(() => {
				 
					this.resize()
				})
			},
			setScrollLeft() {
				// 当前活动tab的布局信息，有tab菜单的width和left(为元素左边界到父元素左边界的距离)等信息
				const tabRect = this.list[this.innerCurrent]
				if(!tabRect){
					return ;
				}
				// 累加得到当前item到左边的距离
				const offsetLeft = this.list
					.slice(0, this.innerCurrent)
					.reduce((total, curr) => {
						return total + curr.rect.width
					}, 0)
				 
				// 此处为屏幕宽度			 
				const windowWidth =  uni.getSystemInfoSync().windowWidth
				// 将活动的tabs-item移动到屏幕正中间，实际上是对scroll-view的移动
				let scrollLeft = offsetLeft - (this.tabsRect.width - tabRect.rect.width) / 2 - (windowWidth - this.tabsRect
					.right) / 2 + this.tabsRect.left / 2
				// 这里做一个限制，限制scrollLeft的最大值为整个scroll-view宽度减去tabs组件的宽度
				scrollLeft = Math.min(scrollLeft, this.scrollViewWidth - this.tabsRect.width)
				this.scrollLeft = Math.max(0, scrollLeft)
			},
			// 获取所有标签的尺寸
			resize() {
				
				// 如果不存在list，则不处理
				if(this.list.length === 0) {
					return
				}
			 
				Promise.all([this.getTabsRect(), this.getAllItemRect()]).then(([tabsRect, itemRect = []]) => {
					this.tabsRect = tabsRect
					this.scrollViewWidth = 0
					 
					itemRect.map((item, index) => {
						// 计算scroll-view的宽度，这里
						this.scrollViewWidth += item.width
						// 另外计算每一个item的中心点X轴坐标
						this.list[index].rect = item
					})
				 
					// 获取了tabs的尺寸之后，设置滑块的位置				 
					this.setScrollLeft()
				})
			},
			// 获取导航菜单的尺寸
			getTabsRect() {
				return new Promise(resolve => {					
					this.queryRect('u-tabs__wrapper__scroll-view').then(size =>  resolve(size)  )
				})
			},
			// 获取所有标签的尺寸
			getAllItemRect() {
				return new Promise(resolve => {					 
					const promiseAllArr = this.list.map((item, index) => this.queryRect(
						`u-tabs__wrapper__nav__item-${index}`, true))
					Promise.all(promiseAllArr).then(sizes =>  resolve(sizes) )
				})
			},
			// 获取各个标签的尺寸
			queryRect(el, item) {			 
				// $uGetRect为uView自带的节点查询简化方法，详见文档介绍：https://ijry.github.io/uview-plus/js/getRect.html
				// 组件内部一般用this.$uGetRect，对外的为uni.$u.getRect，二者功能一致，名称不同
				return new Promise(resolve => {
					 this.uGetRect(`.${el}`).then(size =>  resolve(size) )
				})
				 
			},
			uGetRect(selector, all) {
			    return new Promise((resolve) => {
			        uni.createSelectorQuery()
			            .in(this)[all ? 'selectAll' : 'select'](selector)
			            .boundingClientRect((rect) => {
			                if (all && Array.isArray(rect) && rect.length) {
			                    resolve(rect)
			                }
			                if (!all && rect) {
			                    resolve(rect)
			                }
			            })
			            .exec()
			    })
			},
		}
	}
</script>

<style lang="scss">
	
	.cate-tabs{
		display: flex;	 
		padding-bottom: 10px;	 
		flex-wrap: nowrap;
		justify-content: flex-start;
		
		.sub-cate{
			background-color: #F2F2F2;
			border-radius: 30px;			 
			padding: 7px 20px ;
			margin-right: 10px;
			flex-shrink: 0;
			
		}
		.active{
			background-color: #C8E1FF;
			color: #4A9BF7;
		}
	}
</style>